package com.bclz.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorExample {

    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket，绑定端口
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(6666));
        serverSocketChannel.configureBlocking(false);  //非阻塞
        //2.创建selector,serverSocket注册selector,关心事件（接受连接准备就绪）
        Selector selector=   Selector.open();
        //关心interest事件为accept
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while(true){
            //3. select获取事件发生个数，0表示无事件
            //等待连接，阻塞1000ms
            if(selector.select(1000)==0){
//                System.out.println("1000 ms current no connect...");
                continue;
            }
            //4.获取发生事件的key列表
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                if(key.isAcceptable()){
                    //
                    dealAcceptEvent(serverSocketChannel,selector);
                }else if(key.isReadable()){

                    dealReadEvent(key);
                }else{

                    System.out.println("no interest event...");
                }
                iterator.remove();
            }

        }
    }

    private static void dealReadEvent(SelectionKey key) throws IOException {
        System.out.println("READ......");
        //通过key反向获取到socketChannel
        SocketChannel socketChannel=(SocketChannel)key.channel();
        //得到与channel关联的数据
        ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
        try {
            int read = socketChannel.read(byteBuffer);
            if(read>0){
                System.out.println(new String(byteBuffer.array()));
            }
        }catch (Exception e){

            System.out.println(socketChannel.hashCode()+ "socket channel closed...");
            key.cancel();
            socketChannel.close();
        }


    }


    private static void dealAcceptEvent(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException {
        System.out.println("accept...");
        SocketChannel socketChannel = serverSocketChannel.accept();
        System.out.println("socket连接...生成SocketChannel："+socketChannel.hashCode());
        socketChannel.configureBlocking(false);
        socketChannel.register(selector,SelectionKey.OP_READ,ByteBuffer.allocate(1024));
    }

    public static class SocketClient{


        public static void main(String[] args) throws IOException, InterruptedException {

            SocketChannel socketChannel=SocketChannel.open(new InetSocketAddress("localhost",6666));
            socketChannel.configureBlocking(false);
//            if(!socketChannel.connect(new InetSocketAddress("localhost",6666))){
//                while (!socketChannel.finishConnect()){
//                    System.out.println("等待完成连接...");
//                }
//            }
            socketChannel.write(ByteBuffer.wrap("测试...123".getBytes("utf-8")));

            Thread.sleep(Integer.MAX_VALUE);
        }

    }

}
